# coding:utf-8
import hashlib

import uuid

import requests
from future.moves.urllib.parse import urlparse

from app.config import server_config

URL = server_config.get('vecmdb_api')
KEY = server_config.get("vecmdb_api_key")
SECRET = server_config.get("vecmdb_api_secret")


def generate_unique_uuid(c_type):
    """
    生成唯一的UUID
    """
    return c_type + '-' + str(uuid.uuid4())


def get_cabinet_rent_type(cabinet):
    url = "http://dcportal.iflytekdc.com:18082/api/cabinet/get_cabinet_config.action"

    payload = {'cabinet_code': cabinet}
    files = [

    ]
    headers = {}

    r = requests.request("POST", url, headers=headers, data=payload, files=files)
    try:
        info = r.json()
        detail = info.get('data')
        return detail.get('rent_type')
    except Exception as e:
        return None


def build_api_key(path, params):
    values = "".join([str(params[k]) for k in sorted((params or {}).keys())
                      if k not in ("_key", "_secret") and not isinstance(params[k], (dict, list))])
    _secret = "".join([path, SECRET, values]).encode("utf-8")
    params["_secret"] = hashlib.sha1(_secret).hexdigest()
    params["_key"] = KEY

    return params


# "_type:project",
def get_ci(data):
    payload = build_api_key(urlparse(URL + "/s").path, data)
    return requests.get(URL + "/s", params=payload).json()


def get_attr(model_id):
    url = f"https://model.iflytek.com/api/v0.1/ci_types/{str(model_id)}/attributes"

    payload = build_api_key(urlparse(url).path, {})
    return requests.get(url, params=payload).json()


def get_ci_except_error(payload: dict):
    try:
        url = URL + "/s"

        res = requests.get(url, params=build_api_key(urlparse(url).path, payload))
        if res.status_code not in [200, 201]:
            return False, res.text

        res_data = res.json()
        return True, res_data
    except Exception as e:
        return False, str(e)


def add_ci(data):
    data["exist_policy"] = "replace"
    payload = build_api_key(urlparse(URL).path, data)
    return requests.post(URL, json=payload).json()


# def update_ci(payload, ci_id=None):
#     url = "{url}/{ci_id}".format(url=URL, ci_id=ci_id) if ci_id is not None else URL
#     payload = build_api_key(urlparse(url).path, payload)
#     return requests.put(url, json=payload).json()

def update_ci(payload, ci_id=None):
    url = "{url}/{ci_id}".format(url=URL, ci_id=ci_id) if ci_id is not None else URL

    payload = build_api_key(urlparse(url).path, payload)

    return requests.put(url, json=payload).json()


def delete_ci(ci_id):
    url = "{url}/{ci_id}".format(url=URL, ci_id=ci_id)

    payload = build_api_key(urlparse(url).path, {})

    return requests.delete(url, json=payload).json()


def add_oneops_ci_data(payload: dict, ci_type: str):
    try:
        payload["ci_type"] = ci_type
        res = add_ci(payload)
    except Exception as e:
        return False, str(e)

    return True, res


def update_oneops_ci_data(payload: dict, ci_id: int):
    try:
        res = update_ci(payload, ci_id=ci_id)
    except Exception as e:
        return False, str(e)

    return True, res


def delete_oneops_ci_data(ci_id: int):
    try:
        res = delete_ci(ci_id)
    except Exception as e:
        return False, str(e)

    return True, res


def get_room_detail(_id):
    payload = {
        "q": "_type:IDC,_id:%s" % _id,
        "count": 10,
        "page": 1
    }
    res = get_ci(payload)
    info = res.get('result')

    return info[0]


def get_room_code_zone(room_name, building, floor):
    """获取机房编码与可用区"""
    if not room_name:
        return '', ''
    payload = {}
    if room_name != '北京大族':
        payload = {
            "q": "_type:IDC,serverRoomName:%s" % room_name,
            "count": 10,
            "page": 1
        }
    else:
        if building == '12栋' and (floor == 4 or floor == 5):
            payload = {
                "q": "_type:IDC,serverRoomName:%s,availableZone:%s" % (room_name, '北京可用区B'),
                "count": 10,
                "page": 1
            }
        elif (building == '8栋' and floor == 4) or (building == '12栋' and floor == 3):
            payload = {
                "q": "_type:IDC,serverRoomName:%s,availableZone:%s" % (room_name, '北京可用区E'),
                "count": 10,
                "page": 1
            }
    if not payload:
        return '', ''
    res = get_ci(payload)
    info = res.get('result')
    if not info:
        return '', ''
    d_info = info[0]
    return d_info['roomCode'], d_info['availableZone']


def get_cabinet_id(room_id, building, floor, module, code):
    """获取机柜id"""
    if (not room_id) or (not building) or (not floor):
        return None
    payload = {
        "q": "_type:cabinet,cabinetRoomName:%s,rackBuilding:%s,rackFloor:%s,rackModule:%s,rackCode:%s" % (
            room_id, building, floor, module, code),
        "count": 10,
        "page": 1
    }
    res = get_ci(payload)
    info = res.get('result')
    if info:
        cabinet_id = info[0].get('_id')
    else:
        cabinet_id = None
    return cabinet_id


def get_cabinet_nvwa_id(nvwa_id):
    """获取机柜id"""
    if nvwa_id:
        return None
    payload = {
        "q": "_type:cabinet,nvwaId:%s" % nvwa_id,
        "count": 10,
        "page": 1
    }
    res = get_ci(payload)
    info = res.get('result')
    if info:
        cabinet_id = info[0].get('_id')
    else:
        cabinet_id = None
    return cabinet_id


def get_cabinet_id_by_complete_code(complete_code):
    """获取机柜id"""
    if not complete_code:
        return None
    payload = {
        "q": f"_type:cabinet,completeCabinetCode:{str(complete_code).strip()}",
        "count": 10,
        "page": 1
    }
    res = get_ci(payload)
    info = res.get('result')
    if info:
        cabinet_id = info[0].get('_id')
    else:
        cabinet_id = None
    return cabinet_id


def get_server_id(sn):
    payload = {
        "q": "_type:PhysicalMachineResource,systemSN:%s" % sn,
        "count": 10,
        "page": 1
    }
    res = get_ci(payload)
    info = res.get('result')
    # print(info)
    if info:
        server_id = info[0].get('_id')
    else:
        server_id = None
    return server_id


def parse_query_dict(ci_type: str, query_dict: dict):
    """解析请求字典"""
    query_list = [f"_type:{ci_type}"]
    for k, v in query_dict.items():
        if isinstance(v, list):
            if v:
                if len(v) == 1:
                    v = v[0]
                else:
                    v_v = []
                    for i in v:
                        v_v.append(str(i))

                    v = f"({';'.join(v_v)})"
            # else:
            #     v = ""

        query_list.append(f"{k}:{v}")

    return ','.join(query_list)


def get_one_ops_ci_list(ci_type: str, query_dict: dict, page: int, page_size: int, sort: str = None, fl: str = None):
    """查询模型数据列表"""

    payload = {
        "q": parse_query_dict(ci_type, query_dict)
    }

    if sort:
        payload["sort"] = sort
    if page:
        payload["page"] = page
    if page_size:
        payload["count"] = page_size
    if fl:
        payload["fl"] = fl

    return get_ci_except_error(payload)


def get_computer_room_list():
    """获取机房列表"""
    ok, ret = get_one_ops_ci_list("IDC", {}, page=1, page_size=1000)
    if ok is False:
        return []

    all_ret = []
    for idc_info in ret["result"]:
        computer_room = idc_info["serverRoomName"]
        if computer_room not in all_ret:
            all_ret.append(computer_room)

    return all_ret


def get_available_zone_list():
    """获取可用区列表"""

    ok, ret = get_one_ops_ci_list("IDC", {}, page=1, page_size=1000)
    if ok is False:
        return []

    return [idc_info["availableZone"] for idc_info in ret["result"]]


def get_all_cabinet_list(query_dict: dict):
    ok, ret = get_one_ops_ci_list("cabinet", query_dict, page=1, page_size=100000)
    if ok is False:
        return False, ret

    cabinet_dict = {}
    for cabinet_info in ret["result"]:
        computer_room = cabinet_info["serverRoomName"]
        building = cabinet_info["rackBuilding"]
        floor = cabinet_info["rackFloor"]
        module = cabinet_info["rackModule"]
        cabinet_code = cabinet_info["rackCode"]

        cabinet_name = '/'.join([computer_room, building, f"{floor}层", module, cabinet_code])

        cabinet_dict[cabinet_name] = cabinet_info

    return True, cabinet_dict

